﻿using Bilibili.Common.Log;
using Bilibili.Model.Common;
using Bilibili.Model.Resource;
using Bilibili.Model.Video;
using Newtonsoft.Json.Linq;
using PCLCrypto;
using PCLUntils;
using PCLUntils.Objects;
using PCLUntils.Plantform;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;

namespace Bilibili.Common
{
    public static class Extension
    {
        public static string GetRoot(bool isData)
        {
            if (isData)
            {
                switch (PlantformUntils.System)
                {
                    case Platforms.Windows:
                        {
                            var assemblyLocation = Assembly.GetEntryAssembly()?.Location ?? Assembly.GetExecutingAssembly()?.Location;
                            if (!string.IsNullOrEmpty(assemblyLocation))
                                return Path.GetDirectoryName(assemblyLocation);
                            return AppDomain.CurrentDomain.BaseDirectory;
                        }
                    default:
                        {
                            var root = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "bilibili_michael");
                            if (!Directory.Exists(root))
                                Directory.CreateDirectory(root);
                            return root;
                        }
                }
            }
            else
            {
                var assemblyLocation = Assembly.GetEntryAssembly()?.Location ?? Assembly.GetExecutingAssembly()?.Location;
                if (!string.IsNullOrEmpty(assemblyLocation))
                    return Path.GetDirectoryName(assemblyLocation);
                return AppDomain.CurrentDomain.BaseDirectory;
            }
        }
        public static void Set(this HttpRequestHeaders header, Dictionary<string, string> headers)
        {
            try
            {
                foreach (var item in headers)
                    header.Add(item.Key, item.Value);
            }
            catch { }
        }
        public static CookieContainer CreateCookieContainer(this string cookieString)
        {
            var cookieContainer = new CookieContainer();
            try
            {
                if (cookieString.IsNotEmpty())
                {
                    Uri hostUrl = new Uri("http://bilibili.com");
                    foreach (var cookie in cookieString.Split(';'))
                    {
                        var items = cookie.Split('=');
                        if (items.Length == 2)
                        {
                            string name = items[0].Trim(), value = items[1].Trim();
                            if (name.IsNotEmpty() && value.IsNotEmpty())
                            {
                                var obj = new Cookie(name, value);
                                cookieContainer.Add(hostUrl, obj);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Instance.LogError("CreateCookieContainer", ex);
            }
            return cookieContainer;
        }
        public static string ToMD5(this string input)
        {
            try
            {
                var asymmetricKeyAlgorithmProvider = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Md5);
                var cryptographicKey = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(input, Encoding.UTF8);
                var hashData = asymmetricKeyAlgorithmProvider.HashData(cryptographicKey);
                return WinRTCrypto.CryptographicBuffer.EncodeToHexString(hashData);
            }
            catch { }
            return input;
        }
        public static int ToInt32(this byte[] bytes)
        {
            try
            {
                if (BitConverter.IsLittleEndian)
                    Array.Reverse(bytes);
                return BitConverter.ToInt32(bytes, 0);
            }
            catch { }
            return 0;
        }
        public static bool IsSuccess<T>(this ApiDataModel<T> model)
        {
            if (model.IsEmpty())
                return false;
            return model.Success;
        }
        public static bool IsSuccess<T>(this ReturnModel<T> model)
        {
            if (model.IsEmpty())
                return false;
            return model.Success && model.Data.IsNotEmpty();
        }
        public static string CurrentArchString(this object _)
        {
            return PlantformUntils.System switch
            {
                Platforms.Linux => $"linux-{PlantformUntils.ArchitectureString}",
                Platforms.Windows => $"win-{PlantformUntils.ArchitectureString}",
                _ => $"osx-{PlantformUntils.ArchitectureString}",
            };
        }
        public static bool SameSite(this string fullUrl, string urlName)
        {
            fullUrl = fullUrl.Replace("http://", "").Replace("https://", "").Replace("file:///", "");
            return fullUrl.StartsWith(urlName, StringComparison.OrdinalIgnoreCase);
        }
        public static PlayerModel ToPlayerModel(this PagesModel item, string aid, VideoInfoModels infos)
        {
            PlayerModel models = default;
            try
            {
                if (infos.Movie != null && infos.Movie.movie_status == 1 && infos.Movie.pay_user.status != 0)
                {
                    models = new PlayerModel
                    {
                        Mode = PlayMode.Movie,
                        Aid = aid,
                        Mid = item.cid,
                        No = string.Empty,
                        VideoTitle = item.View
                    };
                }
                else
                {
                    if (infos.Season != null)
                    {
                        models = new PlayerModel
                        {
                            Aid = aid,
                            Mid = item.cid,
                            Mode = PlayMode.Bangumi,
                            VideoTitle = item.View,
                            Episode_Id = infos.Season.Newest_Ep_Id
                        };
                    }
                    else
                    {
                        models = new PlayerModel
                        {
                            Aid = aid,
                            Mid = item.cid,
                            IsInteraction = infos.Interaction != null,
                            Graph_Version = infos.Interaction?.Graph_Version,
                            Mode = PlayMode.Video,
                            VideoTitle = item.View
                        };
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Instance.LogError("ToPlayerModel", ex);
            }
            return models;
        }
        public static List<PlayerModel> ToPlayerModel(this List<PagesModel> items, string aid, VideoInfoModels infos)
        {
            List<PlayerModel> models = new List<PlayerModel>();
            var row = 0;
            foreach (var item in items)
            {
                try
                {
                    if (infos.Movie != null && infos.Movie.movie_status == 1 && infos.Movie.pay_user.status != 0)
                    {
                        models.Add(new PlayerModel
                        {
                            Mode = PlayMode.Movie,
                            Aid = aid,
                            Mid = item.cid,
                            No = string.Empty,
                            VideoTitle = item.View
                        });
                    }
                    else
                    {
                        if (infos.Season != null)
                        {
                            models.Add(new PlayerModel()
                            {
                                Aid = aid,
                                Mid = item.cid,
                                Mode = PlayMode.Bangumi,
                                No = row.ToString(),
                                VideoTitle = item.View,
                                Episode_Id = infos.Season.Newest_Ep_Id
                            });
                        }
                        else
                        {
                            models.Add(new PlayerModel()
                            {
                                Aid = aid,
                                Mid = item.cid,
                                IsInteraction = infos.Interaction != null,
                                Graph_Version = infos.Interaction?.Graph_Version,
                                Mode = PlayMode.Video,
                                No = row.ToString(),
                                VideoTitle = item.View
                            });
                        }
                    }
                    row++;
                }
                catch (Exception ex)
                {
                    LogManager.Instance.LogError("ToPlayerModel", ex);
                }
            }
            return models;
        }
        public static ReturnJObject ToDynamicJObject(this string json)
        {
            try
            {
                var obj = JObject.Parse(json);
                ReturnJObject returnJObject = new ReturnJObject
                {
                    Code = obj["code"].ToInt32(),
                    Message = (obj["message"] == null) ? string.Empty : obj["message"].ToString(),
                    Msg = (obj["msg"] == null) ? string.Empty : obj["msg"].ToString(),
                    Json = obj
                };
                return returnJObject;
            }
            catch
            {
                return new ReturnJObject
                {
                    Code = -999,
                    Message = "解析JSON失败",
                    Msg = "解析JSON失败"
                };
            }
        }
        public static bool IsSuccess(this ReturnPlayModel model)
        {
            if (model.IsEmpty())
                return false;
            return model.Success;
        }
    }
}